home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Programming / SWI / source / src / pl-rl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-04  |  5.5 KB  |  274 lines

  1. /*  $Id: pl-rl.c,v 1.13 1998/02/04 16:22:59 jan Exp $
  2.  
  3.     Copyright (c) 1990 Jan Wielemaker. All rights reserved.
  4.     See ../LICENCE to find out about your rights.
  5.     jan@swi.psy.uva.nl
  6.  
  7.     Purpose: Binding to the GNU readline library
  8. */
  9.  
  10. #ifndef __WIN32__
  11. #include "pl-incl.h"
  12. #endif
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include "pl-stream.h"
  16. #include "pl-itf.h"
  17.  
  18. #ifdef __WIN32__
  19. #include "config/win32.h"
  20. #else
  21. #include <config.h>
  22. #endif
  23.  
  24. #ifdef HAVE_LIBREADLINE
  25.  
  26. #ifdef HAVE_MALLOC_H
  27. #include <malloc.h>
  28. #endif
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #ifdef HAVE_UXNT_H
  33. #include <uxnt.h>
  34. #endif
  35. #ifdef HAVE_CLOCK
  36. #include <time.h>
  37. #endif
  38. #ifdef __WIN32__
  39. #include <io.h>
  40. #endif
  41. #ifdef O_RLC
  42. #include <console.h>
  43. #endif
  44.  
  45. #ifdef HAVE_RL_INSERT_CLOSE
  46. #define PAREN_MATCHING 1
  47. extern int rl_delete_text(int from, int to);
  48. #endif
  49.  
  50. #undef ESC                /* will be redefined ... */
  51. #include <stdio.h>            /* readline needs it */
  52. #define savestring(x)            /* avoid definition there */
  53. #include <readline/readline.h>
  54. extern void add_history(char *);    /* should be in readline.h */
  55. extern int rl_begin_undo_group(void);    /* delete when conflict arrises! */
  56. extern int rl_end_undo_group(void);
  57. extern Function *rl_event_hook;
  58. extern char *filename_completion_function(char *, int);
  59.  
  60.  
  61. static foreign_t
  62. pl_rl_read_init_file(term_t file)
  63. { char *f;
  64.  
  65.   if ( (f = PL_get_filename(file, NULL, 0)) )
  66.   {
  67. #ifdef O_XOS
  68.     char buf[MAXPATHLEN];
  69.     rl_read_init_file(_xos_os_filename(f, buf));
  70. #else
  71.     rl_read_init_file(f);
  72. #endif
  73.  
  74.     PL_succeed;
  75.   }
  76.  
  77.   PL_fail;
  78. }
  79.  
  80.  
  81. static foreign_t
  82. pl_rl_add_history(term_t text)
  83. { char *s;
  84.  
  85.   if ( PL_get_chars(text, &s, CVT_ALL) )
  86.   { add_history(s);
  87.  
  88.     PL_succeed;
  89.   }
  90.  
  91.   return PL_warning("rl_add_history/1: instantation fault");
  92. }
  93.  
  94.  
  95. static int
  96. event_hook()
  97. { return PL_dispatch(0, PL_DISPATCH_NOWAIT);
  98. }
  99.  
  100.  
  101. static int
  102. Sread_readline(void *handle, char *buf, int size)
  103. { long h = (long)handle;
  104.   int fd = (int) h;
  105.   int ttymode = PL_ttymode(fd);
  106.   int rval;
  107. #ifdef HAVE_CLOCK
  108.   long oldclock = clock();
  109. #endif
  110.  
  111.   PL_write_prompt(fd, ttymode == PL_NOTTY);
  112.   
  113.   switch( ttymode )
  114.   { case PL_RAWTTY:            /* get_single_char/1 */
  115. #ifdef O_RLC
  116.     { int chr = getkey();
  117.       
  118.       if ( chr == 04 || chr == 26 )
  119.     return 0;            /* EOF */
  120.  
  121.       buf[0] = chr & 0xff;
  122.       return 1;
  123.     }
  124. #endif
  125.     case PL_NOTTY:            /* -tty */
  126.     { PL_dispatch(fd, PL_DISPATCH_WAIT);
  127.       rval = read(fd, buf, size);
  128.       if ( rval > 0 && buf[rval-1] == '\n' )
  129.     PL_prompt_next(fd);
  130.  
  131.       break;
  132.     }
  133.     case PL_COOKEDTTY:
  134.     default:
  135.     { char *line;
  136.       char *prompt;
  137.  
  138.       if ( PL_dispatch(0, PL_DISPATCH_INSTALLED) )
  139.     rl_event_hook = event_hook;
  140.       else
  141.     rl_event_hook = NULL;
  142.  
  143.       prompt = PL_prompt_string(fd);
  144.       if ( prompt )
  145.     PL_add_to_protocol(prompt, strlen(prompt));
  146.  
  147.       if ( (line = readline(prompt)) )
  148.       { char *s;
  149.     int l = strlen(line);
  150.       
  151.     if ( l > size )
  152.     { PL_warning("Input line too long");    /* must be tested! */
  153.       l = size-1;
  154.     }
  155.     memcpy(buf, line, l);
  156.     buf[l++] = '\n';
  157.     rval = l;
  158.  
  159.     for(s = line; *s; s++)
  160.     { if ( (*s & 0xff) > ' ' )
  161.         break;
  162.     }
  163.  
  164.         if ( !*s )            /* blanks only! */
  165.       free(line);
  166.       } else
  167.     rval = 0;
  168.     }
  169.   }
  170.  
  171.   if ( ttymode != PL_RAWTTY )
  172.   { PL_add_to_protocol(buf, rval);
  173.   }
  174.  
  175. #ifdef HAVE_CLOCK
  176.   PL_clock_wait_ticks(clock() - oldclock);
  177. #endif
  178.  
  179.   return rval;
  180. }
  181.  
  182.  
  183. static void
  184. prolog_complete(int ignore, int key)
  185. { if ( rl_point > 0 && rl_line_buffer[rl_point-1] != ' ' )
  186.   { rl_begin_undo_group();
  187.     rl_complete(ignore, key);
  188.     if ( rl_point > 0 && rl_line_buffer[rl_point-1] == ' ' )
  189.     {
  190. #ifdef HAVE_RL_INSERT_CLOSE        /* actually version >= 1.2 */
  191.       rl_delete_text(rl_point-1, rl_point);
  192.       rl_point -= 1;
  193. #else
  194.       rl_delete(-1);
  195. #endif
  196.     }
  197.     rl_end_undo_group();
  198.   } else
  199.     rl_complete(ignore, key);
  200. }
  201.  
  202.  
  203. static char *
  204. atom_generator(char *prefix, int state)
  205. { char *s = PL_atom_generator(prefix, state);
  206.   
  207.   if ( s )
  208.     return strcpy(xmalloc(1 + strlen(s)), s);
  209.  
  210.   return s;
  211. }
  212.  
  213.  
  214. static char **
  215. prolog_completion(char *text, int start, int end)
  216. { char **matches = NULL;
  217.  
  218.   if ( (start == 1 && rl_line_buffer[0] == '[') )    /* [file */
  219.     matches = completion_matches(text,
  220.                  (Function *) filename_completion_function);
  221.   else if (start == 2 && strncmp(rl_line_buffer, "['", 2))
  222.     matches = completion_matches(text,
  223.                  (Function *) filename_completion_function);
  224.   else
  225.     matches = completion_matches(text, atom_generator);
  226.  
  227.   return matches;
  228. }
  229.  
  230. #undef read                /* UXNT redefinition */
  231.  
  232. install_t
  233. PL_install_readline()
  234. #ifndef __WIN32__
  235.   if ( GD->cmdline.notty || !isatty(0) )
  236.     return;
  237. #endif
  238.  
  239.   rl_readline_name = "Prolog";
  240.   rl_attempted_completion_function = prolog_completion;
  241. #ifdef __WIN32__
  242.   rl_basic_word_break_characters = "\t\n\"\\'`@$><= [](){}+*!,|%&?";
  243. #else
  244.   rl_basic_word_break_characters = ":\t\n\"\\'`@$><= [](){}+*!,|%&?";
  245. #endif
  246.   rl_add_defun("prolog-complete", (Function *) prolog_complete, '\t');
  247. #if HAVE_RL_INSERT_CLOSE
  248.   rl_add_defun("insert-close", rl_insert_close, ')');
  249. #endif
  250.  
  251.   GD->os.rl_functions = *Sinput->functions;    /* structure copy */
  252.   GD->os.rl_functions.read = Sread_readline;    /* read through readline */
  253.  
  254.   Sinput->functions  = &GD->os.rl_functions;
  255.   Soutput->functions = &GD->os.rl_functions;
  256.   Serror->functions  = &GD->os.rl_functions;
  257.  
  258.   PL_register_foreign("rl_read_init_file", 1, pl_rl_read_init_file, 0);
  259.   PL_register_foreign("rl_add_history",    1, pl_rl_add_history,
  260.               PL_FA_NOTRACE);
  261.   PL_set_feature("readline", PL_ATOM, "true");
  262.   PL_set_feature("tty_control", PL_ATOM, "true");
  263. }
  264.  
  265. #else /*HAVE_LIBREADLINE*/
  266.  
  267. install_t
  268. PL_install_readline()
  269. {
  270. }
  271.  
  272. #endif /*HAVE_LIBREADLINE*/
  273.